
#include "HrkMesh.h"
#include "HrkModel.h"
#include "tinyxml/tinyxml.h"

#pragma warning( disable:4996)
IMPLEMENT_DYNCREATE( CHrkMesh,CHrkObject )

CHrkMesh::CHrkMesh()
{
	m_pModel = NULL;
}

void CHrkMesh::UpdateTransform()
{
}

void CHrkMesh::ParseScript( TiXmlElement* elem )
{
	const char*s =elem->Attribute("name");
	TiXmlElement* elem1 = elem->FirstChildElement("Mesh");
	
	TiXmlElement* e = NULL;
	int count = 0;		
	const char*strText = NULL;
	char *tmpChar = NULL; 
	
	if(elem1){
		m_name = elem1->Attribute( "name" );
	
		m_posVec.SetEmpty();
		m_posVec.reserve( count );
		
		e = elem1->FirstChildElement( "MeshPositions" );
		count = atoi( e->Attribute("count"));
		strText = e->GetText();
		tmpChar = strtok((char*)strText, ";");  

		for (int i = 0; i < count; i++) {
			GLvec3f v;
			int ret = sscanf(tmpChar, "%f,%f,%f;", &v.x, &v.y, &v.z);

			tmpChar = strtok(NULL, ";");
			m_posVec.push_back(v);
		}

		e = elem1->FirstChildElement( "MeshNormals" );
		count = atoi( e->Attribute("count"));
		strText = e->GetText();
		tmpChar = strtok((char*)strText, ";");  

		for (int i = 0; i < count; i++) {
			GLvec3f v;
			int ret = sscanf(tmpChar, "%f,%f,%f;", &v.x, &v.y, &v.z);

			tmpChar = strtok(NULL, ";"); 
			m_normalVec.push_back(v);
		}

		e = elem1->FirstChildElement( "MeshTextureCoords" );
		count = atoi( e->Attribute("count"));
		strText = e->GetText();
		tmpChar = strtok((char*)strText, ";");  

		for (int i = 0; i < count; i++) {
			GLvec2f v;
			int ret = sscanf(tmpChar, "%f,%f;", &v.x, &v.y);

			tmpChar = strtok(NULL, ";"); 
			m_tcVec.push_back(v);
		}

		e = elem1->FirstChildElement( "MeshVertexColors" );
		count = atoi( e->Attribute("count"));
		strText = e->GetText();
		tmpChar = strtok((char*)strText, ";");  

		for (int i = 0; i < count; i++) {
			GLvec4f v;
			int ret = sscanf(tmpChar, "%f,%f,%f,%f;", &v.x, &v.y,&v.z,&v.w);

			tmpChar = strtok(NULL, ";"); 
			m_vcVec.push_back(v);
		}

		
 
		TiXmlElement* e1 = elem1->FirstChildElement( "SubMesh" );

		while(e1){
  
			TiXmlElement* e2 = e1->FirstChildElement("Faces");
			TiXmlElement* e3 = e1->FirstChildElement("Material");		

			int pt = FT_TRILIST;

			const char* s = e2->Attribute( "type" );

			if(s){
				if( strcmp( s,"Strip") == 0){
					pt = FT_TRISTRIP;
				}		
			}
			
			count = atoi( e2->Attribute("count") );
			strText = e2->GetText();
			tmpChar = strtok((char*)strText, ";");  	
			
			CHrkSubMesh* subMesh = new CHrkSubMesh;	
			subMesh->m_pMesh = this;
			
			const char* mat_name = e3->Attribute("name");
			subMesh->m_pMaterial = m_pModel->FindMaterial( mat_name );
			subMesh->m_ob_type = HRK_SUBMESH;
			m_subMeshesVec.push_back(subMesh);

			CHrkIndexBuffer*indexBuffer = NULL;
			
			if( pt == FT_TRILIST ){
				indexBuffer = new CHrkIndexBuffer( FT_TRILIST );		
				indexBuffer->m_faceIndices.SetEmpty();
				subMesh->m_indexBuffers.push_back( indexBuffer );
				indexBuffer->m_faceIndices.reserve( count*3 );

				for ( int i = 0; i < count; i++) {
					GLvec3f v;
					int ret = sscanf(tmpChar, "%d,%d,%d;", &v.x, &v.y, &v.z);
					tmpChar = strtok(NULL, ";");  
					indexBuffer->m_faceIndices.push_back(v.x);
					indexBuffer->m_faceIndices.push_back(v.y);
					indexBuffer->m_faceIndices.push_back(v.z);
				}
			}
			else if( pt == FT_TRISTRIP ){
				int indexNum = 0;
				for ( int i = 0; i < count; ) {
					DWORD indexCount;
					DWORD index;
					sscanf(tmpChar, "%d;", &indexCount);
					tmpChar = strtok(NULL, ";");  

					indexBuffer = new CHrkIndexBuffer( FT_TRISTRIP );		
					indexBuffer->m_faceIndices.SetEmpty();
					subMesh->m_indexBuffers.push_back( indexBuffer );
					indexBuffer->m_faceIndices.reserve( indexCount );

					for (unsigned int j = 0; j < indexCount; j++) {
						int ret = sscanf(tmpChar, "%d", &index);
						indexBuffer->m_faceIndices.push_back(index);
						
						tmpChar=strpbrk(tmpChar, ",")+1;
					}
					i += (indexCount-2);
					tmpChar = strtok(NULL, ";");  
				}
			}
			
			e1 = e1->NextSiblingElement("SubMesh");
		
		}

		e1 = elem1->FirstChildElement( "SkinBone" );


		if( e1 ){

			TiXmlElement* e2 = e1->FirstChildElement("Bone");

			while( e2 ){
				
				TiXmlElement* e3 = e2->FirstChildElement("OffsetMatrix");
				const char* s = e3->GetText();

				tSkinBone skinBone;

				skinBone.boneName = e2->Attribute("name");
				int boneIndex = m_pModel->FindBoneIndex( skinBone.boneName.c_str() );
				int skinVerts = atoi( e2->Attribute("SkinVerts") );
				
				GLmat4f& m = skinBone.offsetMatrix;
				sscanf(s,"%f,%f,%f,%f,"
					"%f,%f,%f,%f,"
					"%f,%f,%f,%f,"
					"%f,%f,%f,%f",
					&m.x.x,&m.x.y,&m.x.z,&m.x.w,
					&m.y.x,&m.y.y,&m.y.z,&m.y.w,
					&m.z.x,&m.z.y,&m.z.z,&m.z.w,
					&m.w.x,&m.w.y,&m.w.z,&m.w.w
				);

				e3 = e2->FirstChildElement("SkinWeight");
				int numSkinIndices = atoi( e3->Attribute("count"));
				
				skinBone.numSkinVert = numSkinIndices;
				skinBone.vIndices = new int[numSkinIndices];
				skinBone.wArrays = new float[numSkinIndices];

				s = e3->GetText();

				char *tmpChar = strtok((char*)s, ";");  
				
				int indexNum;
				int index[256];
				float weight;

				int vertIndex = 0;
			
				for (int i = 0; i < skinVerts; i++) {
					
					sscanf(tmpChar, "%d", &indexNum);
					tmpChar = strtok(NULL, ";");  
					
					sscanf(tmpChar, "%f", &weight);
					tmpChar = strtok(NULL, ";"); 

					assert( indexNum<=256 );

					for (int j = 0; j < indexNum; j++) {
						sscanf(tmpChar, "%d", &index[j]);
						tmpChar=strpbrk(tmpChar, ",")+1;
						skinBone.vIndices[vertIndex] = index[j];
						skinBone.wArrays[vertIndex] = weight;
						vertIndex++;
					}

					tmpChar = strtok(NULL, ";");  
				}

				m_skinBonesVec.push_back( skinBone );
				e2 = e2->NextSiblingElement( "Bone");
			}
					
		}	
	}
}